package ru.compscicenter.uno.controller;

import ru.compscicenter.uno.model.*;
import ru.compscicenter.uno.view.View;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.sql.Array;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

/**
 * User: SLeeP
 * Date: 04.11.11
 * Time: 20:33
 */
public abstract class AController extends Thread implements IModel {
    public static final String NAMES = "NAMES";
    public static final String CONNECT = "CONNECT";
    public static final String DISCONNECT = "DISCONNECT";
    public static final String RULES = "RULES";
    public static final String MODEL_DATA = "MODEL_DATA";
    public static final String PLAYERS = "PLAYERS";
    public static final String DECK = "DECK";
    public static final String DO_DROP_CARD = "DO_DROP_CARD";
    public static final String DO_TAKE_CARD = "DO_TAKE_CARD";
    public static final String DO_SAY_UNO = "DO_SAY_UNO";
    public static final String DO_SAY_NO_UNO = "DO_SAY_NO_UNO";
    public static final String DO_END_TURN = "DO_END_TURN";
    public static final String DO_START_ROUND = "DO_START_ROUND";
    public static final String SUCCESS = "SUCCESS";
    public static final String ERROR = "ERROR";

    protected int lastOperationSucceed = -2;

    protected Model model;
    protected boolean isChanged = false;
    public boolean isReady = false;
    protected final boolean isServer;
    private View view;

    protected AController(boolean server) {
        isServer = server;
    }

    public boolean isServer() {
        return isServer;
    }

    public boolean isReady() {
        return isReady;
    }

    public void setReady(boolean ready) {
        isReady = ready;
    }

    public View getView() {
        return view;
    }

    public void setView(View view) {
        this.view = view;
        model.setView(view);
    }

    public int getCurrentPlayerId() {
        return model.getCurrentPlayerId();
    }

    public Model getModel() {
        return model;
    }

    public boolean isChanged() {
        return isChanged;
    }


    public void setIsChanged(boolean isChanged) {
        this.isChanged = isChanged;
    }

    public int getRoundWinnerPlayerId() {
        return model.getRoundWinnerPlayerId();
    }

    public void updateModelData(String representation) {
        isChanged = true;
        model = StringRepresentation.modelFromStringRepresentation(representation);
        model.setView(view);
        model.setGameStateProcess();
        isReady = true;
        model.setCurrentPlayerId(0);
    }

    public int getGameWinnerPlayerId() {
        return model.getGameWinnerPlayerId();
    }

    public String whatIsMyIP() {
        Enumeration<NetworkInterface> ni = null;
        int i = 1;
        ArrayList<String> addresses = new ArrayList<String>();
        System.out.println("Choose network interface from: ");
        try {
            ni = NetworkInterface.getNetworkInterfaces();
            while (ni.hasMoreElements()) {
                NetworkInterface niElement = ni.nextElement();
                if (!niElement.isLoopback()) {
                    Enumeration<InetAddress>  ia = niElement.getInetAddresses();
                    while (ia.hasMoreElements()) {
                        InetAddress address = ia.nextElement();
                        if (address instanceof Inet4Address) {
                            addresses.add(address.toString().substring(1));
                            System.out.println("   " + i++ + ". " + address.toString().substring(1));
                        }
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }

        System.out.println("Write number of appropriate network interface: ");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
            int pos = Integer.parseInt(br.readLine());
            return addresses.get(pos - 1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;

    }

    public void setCurrentPlayerId(int currentPlayerId) {
        model.setCurrentPlayerId(currentPlayerId);
    }

    public int getMyPlayerId() {
        return model.getMyPlayerId();
    }

    public void setMyPlayerId(int myPlayerId) {
        model.setMyPlayerId(myPlayerId);
    }

    public List<Player> getPlayers() {
        return model.getPlayers();
    }

    public boolean isClockwise() {
        return model.isClockwise();
    }

    public Card getTopCard() {
        return model.getTopCard();
    }

	public Card.Color getTopColor() {
		return model.getTopColor();
	}

    public int getTakingDeckSize() {
        return model.getTakingDeckSize();
    }

    public int getDroppedDeckSize() {
        return model.getDroppedDeckSize();
    }

    public int getPlayersCount() {
        return model.getPlayersCount();
    }

    public boolean isRoundEnded() {
        return model.isRoundEnded();
    }

    public boolean isGameEnded() {
        return model.isGameEnded();
    }

    public boolean isGameRunning() {
        return model.isGameRunning();
    }

    public boolean addPlayer(Player player) {
        return model.addPlayer(player);
    }

    public boolean removePlayer(int playerId) {
        return model.removePlayer(playerId);
    }

    public Player getPlayer(int id) {
        return model.getPlayer(id);
    }

    public int nextPlayerId() {
        return model.nextPlayerId();
    }

    public int nextPlayerId(int playerId) {
        return model.nextPlayerId(playerId);
    }

    public int getPointsToWin() {
        return model.getPointsToWin();
    }

    public void setRules(Rules rules) {
        model.setRules(rules);
    }

    public Rules getRules() {
        return model.getRules();
    }

    public void setPointsToWin(int pointsToWin) {
        model.setPointsToWin(pointsToWin);
    }

    public List<Card> getTakingDeck() {
        return model.getTakingDeck();
    }

    public void setTakingDeck(LinkedList<Card> takingDeck) {
        model.setTakingDeck(takingDeck);
    }

    public List<Card> getDroppedDeck() {
        return model.getDroppedDeck();
    }

    public void setDroppedDeck(LinkedList<Card> droppedDeck) {
        model.setDroppedDeck(droppedDeck);
    }

    public int getLastOperationSucceed() {
        return lastOperationSucceed;
    }

    public void setLastOperationSucceed(int lastOperationSucceed) {
        this.lastOperationSucceed = lastOperationSucceed;
    }

    public boolean isIDidSomething() {
        return model.isIDidSomething();
    }
}
